<template>
  <div class="app-container">
    <div class="operation-bar">
      <div class="switch-wrapper">
        <el-switch
          v-model="draggable"
          active-text="开启拖拽"
          inactive-text="关闭拖拽"
          active-color="#1890ff"
          inactive-color="#ccc"
          @change="handleDragSwitch"
        />
      </div>
      <div class="btn-group">
        <el-button 
          v-if="draggable" 
          @click="batchSave" 
          type="primary"
          size="mini"
          icon="el-icon-save"
          class="btn-with-margin"
        >
          批量保存
        </el-button>
        <el-button 
          @click="batchDelete" 
          type="danger"
          size="mini"
          icon="el-icon-delete"
          class="btn-with-margin"
        >
          批量删除
        </el-button>
      </div>
    </div>

    <!-- 树形组件：添加卡片容器，优化阴影和内边距 -->
    <div class="tree-card">
      <el-tree 
        :data="categoryTreeData" 
        :props="defaultProps" 
        @node-click="handleNodeClick"
        node-key="catId"
        :expand-on-click-node="false"
        :render-content="renderContent"
        show-checkbox
        :default-expanded-keys="expendKey"
        :draggable="draggable"
        :allow-drop="allowDrop"
        @node-drop="handleDrop"
        ref="categoryTree"
        v-hasPermi="['sproduct:category:edit']"
        class="custom-tree"
        :loading="loading"
      >
        <span class="custom-tree-node" slot-scope="{ node, data }" >
          <!-- 节点文本：添加层级缩进标识 -->
          <span class="node-label">
            <span v-for="(item, index) in node.level - 1" :key="index" class="level-indent"></span>
            <span v-if="node.level > 1" class="level-line"></span>
            {{ node.label }}
          </span>
          <!-- 节点操作按钮：hover时显示，优化间距 -->
          <span class="node-actions">
            <el-button 
              v-if="node.level <= 3" 
              type="text" 
              size="mini" 
              @click="() => append(data)"
              class="action-btn"
              icon="el-icon-plus"
            >
              添加
            </el-button>
            <el-button 
              type="text" 
              size="mini" 
              @click="() => edit(data)"
              class="action-btn"
              icon="el-icon-edit"
            >
              编辑
            </el-button>
            <el-button 
              v-if="node.childNodes.length === 0" 
              type="text" 
              size="mini" 
              @click="() => remove(data)"
              class="action-btn danger-btn"
              icon="el-icon-delete"
            >
              删除
            </el-button>
          </span>
        </span>
      </el-tree>
      <!-- 空数据占位 -->
      <div v-if="!loading && categoryTreeData.length === 0" class="empty-tree">
        <el-empty description="暂无分类数据，请添加"></el-empty>
      </div>
    </div>

    <!-- 分页组件：固定在底部，居中显示 -->
    <div class="pagination-container">
      <pagination
        v-show="total>0"
        :total="total"
        :page.sync="queryParams.pageNum"
        :limit.sync="queryParams.pageSize"
        @pagination="getList"
        layout="total, sizes, prev, pager, next, jumper"
      />
    </div>

    <!-- 分类编辑弹窗：优化表单布局，统一样式 -->
    <el-dialog 
      :title="title" 
      :visible.sync="dialogVisible" 
      :close-on-click-modal="false"
      width="500px"
      :before-close="handleDialogClose"
      class="custom-dialog"
    >
      <el-form 
        :model="form" 
        ref="categoryForm"
        label-width="100px"
        class="form-container"
      >
        <el-form-item 
          label="分类名称" 
          prop="name"
          :rules="[{ required: true, message: '请输入分类名称', trigger: 'blur' }]"
        >
          <el-input 
            v-model="form.name" 
            autocomplete="off"
            placeholder="请输入分类名称"
            class="form-input"
          ></el-input>
        </el-form-item>
        <el-form-item 
          label="分类图标" 
          prop="icon"
          :rules="[{ required: true, message: '请输入图标地址', trigger: 'blur' }]"
        >
          <el-input 
            v-model="form.icon" 
            autocomplete="off"
            placeholder="请输入图标地址（如：/static/icon/cat1.png）"
            class="form-input"
          ></el-input>
        </el-form-item>
        <el-form-item 
          label="计量单位" 
          prop="productUnit"
          :rules="[{ required: true, message: '请输入计量单位', trigger: 'blur' }]"
        >
          <el-input
            v-model="form.productUnit"
            autocomplete="off"
            placeholder="请输入计量单位（如：件、个、套）"
            class="form-input"
          ></el-input>
        </el-form-item>
        <el-form-item 
          label="显示状态" 
          prop="showStatus"
          :rules="[{ required: true, message: '请选择显示状态', trigger: 'change' }]"
        >
          <el-select 
            v-model="form.showStatus" 
            placeholder="请选择显示状态"
            class="form-select"
          >
            <el-option
              v-for="dict in dict.type.pms_category_show_status"
              :key="dict.value"
              :label="dict.label"
              :value="parseInt(dict.value)"
            ></el-option>
          </el-select>
        </el-form-item>
        <el-form-item 
          label="排序" 
          prop="sort"
          :rules="[{ required: true, message: '请输入排序号', trigger: 'blur' }, { type: 'number', message: '请输入数字', trigger: 'blur' }]"
        >
          <el-input
            v-model="form.sort"
            autocomplete="off"
            placeholder="数字越小，排序越靠前"
            class="form-input"
          ></el-input>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="closeCategory" size="mini">取 消</el-button>
        <el-button type="primary" @click="submitForm" size="mini">确 定</el-button>
      </div>
    </el-dialog>

    <!-- 商品三级分类对话框：已整合到上方弹窗，保留兼容结构 -->
    <el-dialog 
      :title="title" 
      :visible.sync="open" 
      width="500px" 
      append-to-body
      :before-close="handleDialogClose"
      class="custom-dialog"
    >
      <el-form 
        ref="form" 
        :model="form" 
        :rules="rules" 
        label-width="100px"
        class="form-container"
      >
        <el-form-item label="分类名称" prop="name">
          <el-input 
            v-model="form.name" 
            placeholder="请输入分类名称"
            class="form-input"
          />
        </el-form-item>
        <el-form-item label="是否显示" prop="showStatus">
          <el-select 
            v-model="form.showStatus" 
            placeholder="请选择是否显示"
            class="form-select"
          >
            <el-option
              v-for="dict in dict.type.pms_category_show_status"
              :key="dict.value"
              :label="dict.label"
              :value="parseInt(dict.value)"
            ></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="排序" prop="sort">
          <el-input 
            v-model="form.sort" 
            placeholder="请输入排序"
            class="form-input"
          />
        </el-form-item>
        <el-form-item label="图标地址" prop="icon">
          <el-input 
            v-model="form.icon" 
            placeholder="请输入图标地址"
            class="form-input"
          />
        </el-form-item>
        <el-form-item label="计量单位" prop="productUnit">
          <el-input 
            v-model="form.productUnit" 
            placeholder="请输入计量单位"
            class="form-input"
          />
        </el-form-item>
        <el-form-item label="商品数量" prop="productCount">
          <el-input 
            v-model="form.productCount" 
            placeholder="请输入商品数量"
            class="form-input"
          />
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="submitForm" size="mini">确 定</el-button>
        <el-button @click="cancel" size="mini">取 消</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import { listCategory, getCategory, delCategory, addCategory, updateCategory, logicDelCategory, updateCategoryBatch } from "@/api/product/category"

export default {
  name: "Category",
  dicts: ['pms_category_show_status'],
  data() {
    return {
      expendKey: [],
      loading: true,
      ids: [],
      single: true,
      multiple: true,
      total: 0,
      categoryList: [],
      title: "",
      open: false,
      queryParams: {
        pageNum: 1,
        pageSize: 10,
        name: null,
        parentCid: null,
        catLevel: null,
        showStatus: 1,
        sort: null,
      },
      form: {
        catId: null,
        name: null,
        parentCid: null,
        catLevel: null,
        showStatus: 1,
        sort: 0,
        icon: null,
        productUnit: null,
        productCount: null
      },
      rules: {
        name: [{ required: true, message: '请输入分类名称', trigger: 'blur' }],
        showStatus: [{ required: true, message: '请选择显示状态', trigger: 'change' }],
        sort: [{ required: true, message: '请输入排序', trigger: 'blur' }, { type: 'number', message: '请输入数字', trigger: 'blur' }],
        icon: [{ required: true, message: '请输入图标地址', trigger: 'blur' }],
        productUnit: [{ required: true, message: '请输入计量单位', trigger: 'blur' }]
      },
      categoryTreeData: [], 
      defaultProps: {
        children: 'children',
        label: 'name'
      },
      dialogVisible: false,
      updateNodes: [],
      maxLevel: 0,
      draggable: true, 
      currentNodeId: null
    }
  },
  created() {
    this.getList()
  },
  methods: {
    // 拖拽开关变化提示
    handleDragSwitch(val) {
      this.$message.info(val ? '已开启拖拽，可调整分类顺序' : '已关闭拖拽，禁止调整顺序');
    },
    // 弹窗关闭前重置表单
    handleDialogClose() {
      this.$refs.categoryForm && this.$refs.categoryForm.resetFields();
      this.reset();
    },
    /** 查询商品三级分类列表 */
    getList() {
      this.loading = true
      return listCategory(this.queryParams).then(response => {
        this.categoryTreeData = this.filterShowStatus(response.data, 1)
        this.loading = false
        return response
      }).catch(error => {
        this.loading = false
        this.$message.error('分类数据加载失败，请重试');
        throw error
      })
    },
    // 取消按钮
    cancel() {
      this.open = false
      this.reset()
    },
    // 表单重置
    reset() {
      this.form = {
        catId: null,
        name: null,
        parentCid: null,
        catLevel: null,
        showStatus: 1,
        sort: 0,
        icon: null,
        productUnit: null,
        productCount: null
      }
      this.$refs.form && this.$refs.form.resetFields();
    },
    /** 搜索按钮操作 */
    handleQuery() {
      this.queryParams.pageNum = 1
      this.getList()
    },
    /** 重置按钮操作 */
    resetQuery() {
      this.$refs.queryForm && this.$refs.queryForm.resetFields();
      this.handleQuery()
    },
    // 多选框选中数据
    handleSelectionChange(selection) {
      this.ids = selection.map(item => item.catId)
      this.single = selection.length!==1
      this.multiple = !selection.length
    },
    /** 新增按钮操作 */
    append(data) {
      this.reset();
      this.form.parentCid = data.catId;
      this.form.catLevel = data.catLevel + 1;
      this.dialogVisible = true;
      this.title = "添加商品分类";
    },
    /**添加商品分类 */
    addCategory() {
      this.$refs.categoryForm.validate((isValid) => {
        if (!isValid) return;
        addCategory(this.form).then(response => {
          this.dialogVisible = false;
          this.$message.success("菜单保存成功");
          this.reset();
          this.getList();
          if (this.form.parentCid) {
            setTimeout(() => {
              this.expendKey = [this.form.parentCid];
            }, 100);
          }
        }).catch(() => {
          this.$message.error("新增失败");
        });
      });
    },
    closeCategory() {
      this.dialogVisible = false;
      this.reset();
    },
    /** 修改按钮操作 */
    edit(data) {
      this.dialogVisible = true;
      this.title = "修改商品分类";
      getCategory(data.catId).then(response => {
        this.form = response.data;
      });
    },        
    // 编辑分类方法
    editCategory() {
      this.$refs.categoryForm.validate((isValid) => {
        if (!isValid) return;
        updateCategory(this.form).then(response => {
          this.$message.success("修改成功");
          this.dialogVisible = false;
          this.getList();
          if (this.form.parentCid) {
            setTimeout(() => {
              this.expendKey = [this.form.parentCid];
            }, 100);
          }
          this.reset();
        }).catch(() => {
          this.$message.error("修改失败");
        });
      });
    },
    //层级计算
    allowDrop(draggingNode, dropNode, type) {
      this.maxLevel = 0;
      this.countNodeLevel(draggingNode.data);
      let possibleLevel;
      if (type === "inner") {
        possibleLevel = dropNode.level + 1;
      } else {
        possibleLevel = dropNode.level;
      }
      const childMaxLevel = this.maxLevel;
      const dragNodeLevel = draggingNode.data.catLevel;
      const levelDiff = possibleLevel - dragNodeLevel;
      
      // 移除警告提示，只返回布尔值
      return (childMaxLevel + levelDiff) <= 3;
    },
    // 拖拽完成事件
    handleDrop(draggingNode, dropNode, dropType, ev) {
      this.updateNodes = [];
      let pCid = 0;
      let siblings = null;
      if (dropType === "before" || dropType === "after") {
        pCid = dropNode.parent.data?.catId || 0;
        siblings = dropNode.parent.childNodes;
      } else if (dropType === "inner") {
        pCid = dropNode.data.catId;
        siblings = dropNode.childNodes;
      }
      if (!siblings) {
        this.$message.error('无法获取同级节点列表');
        return;
      }
      for (let i = 0; i < siblings.length; i++) {
        const currentNode = siblings[i];
        if (!currentNode.data || !currentNode.data.catId) continue;
        if (currentNode.data.catId === draggingNode.data.catId) {
          let catLevel = currentNode.level;
          if (currentNode.level !== draggingNode.level) {
            this.updateChildNodeLevel(currentNode);
          }
          this.updateNodes.push({
            catId: currentNode.data.catId,
            sort: i,
            parentCid: pCid,
            catLevel: catLevel,
          });
        } else {
          this.updateNodes.push({ 
            catId: currentNode.data.catId, 
            sort: i 
          });
        }
      }
    },
    /** 求当前节点的最大子节点深度 */
    countNodeLevel(node) {
      if (node.catLevel > this.maxLevel) {
        this.maxLevel = node.catLevel;
      }
      if (node.children && node.children.length > 0) {
        for (let i = 0; i < node.children.length; i++) {
          this.countNodeLevel(node.children[i]);
        }
      }
    },
    // 更新孩子节点层级
    updateChildNodeLevel(node) {
      const length = node.childNodes ? node.childNodes.length : 0;
      if (length > 0) {
        for (let i = 0; i < length; i++) {
          let cNode = node.childNodes[i].data;
          this.updateNodes.push({
            catId: cNode.catId,
            catLevel: node.childNodes[i].level,
          });
          this.updateChildNodeLevel(node.childNodes[i]);
        }
      }
    },
    // 拖拽保存
    batchSave() {
      if (this.updateNodes.length === 0) {
        this.$message.warning("没有需要保存的变更");
        return;
      }
      const validNodes = this.updateNodes.map(node => ({
        catId: node.catId,
        sort: node.sort !== undefined ? node.sort : 0,
        parentCid: node.parentCid !== undefined ? node.parentCid : 0,
        catLevel: node.catLevel !== undefined ? node.catLevel : 1
      }));
      this.loading = true;
      updateCategoryBatch(validNodes).then(response => {
        if (response && response.code === 200) {
          this.$message.success("菜单顺序修改成功");
          const currentNodeId = this.currentNodeId;
          this.getList().then(() => {
            if (currentNodeId) {
              this.$nextTick(() => {
                this.expendKey = [currentNodeId];
              });
            }
          });
          this.updateNodes = [];
          this.maxLevel = 0;
        } else {
          const errorMsg = response?.msg || response?.message || '后端处理异常';
          this.$message.error(`更新失败：${errorMsg}`);
        }
        this.loading = false;
      }).catch(error => {
        console.error("批量更新请求异常：", error);
        this.$message.error(error?.message ? `请求异常：${error.message}` : "更新失败，请检查网络或联系管理员");
        this.loading = false;
      });
    },
    // 在node-click事件中记录当前选中节点
    handleNodeClick(data) {
      this.currentNodeId = data.catId;
    },
    // 批量删除分类
    batchDelete() {
      let selectedNodes = this.$refs.categoryTree.getCheckedNodes();
      if (!selectedNodes || selectedNodes.length === 0) {
        this.$message.warning("请先选择要删除的分类");
        return;
      }
      let catIds = selectedNodes.map(node => node.catId);
      this.$confirm(`是否确认批量删除选中的 ${catIds.length} 个分类？`, "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      }).then(() => {
        this.loading = true;
        return logicDelCategory(catIds);
      }).then(response => {
        if (response && response.code === 200) {
          this.$message.success("批量删除成功");
          this.getList();
          this.$refs.categoryTree.setCheckedKeys([]);
        } else {
          const errorMsg = response?.msg || response?.message || '删除失败';
          this.$message.error(errorMsg);
        }
      }).catch(error => {
        if (error !== 'cancel' && error !== 'close') {
          console.error("批量删除异常：", error);
          this.$message.error("删除失败，请重试");
        } else {
          this.$message.info("已取消删除");
        }
      }).finally(() => {
        this.loading = false;
      });
    },
    /** 提交按钮 */
    submitForm() {
      if (this.form.catId != null) {
        this.editCategory();
      } else {
        this.addCategory();
      }
    },
    /** 删除按钮操作 */
    handleDelete(row) {
      const catIds = row.catId || this.ids
      this.$modal.confirm('是否确认删除商品三级分类编号为"' + catIds + '"的数据项？').then(function() {
        return delCategory(catIds)
      }).then(() => {
        this.getList()
        this.$modal.msgSuccess("删除成功")
      }).catch(() => {})
    },
    /** 导出按钮操作 */
    handleExport() {
      this.download('product/category/export', {
        ...this.queryParams
      }, `category_${new Date().getTime()}.xlsx`)
    },
    /** 过滤显示状态数据 */
    filterShowStatus(data, showStatus) {
      return data.filter(item => {
        const matches = item.showStatus == showStatus
        if (item.children && item.children.length > 0) {
          item.children = this.filterShowStatus(item.children, showStatus)
        }
        return matches || (item.children && item.children.length > 0)
      })
    },
    /** 删除菜单 */
    remove(data) {
      const ids = [data.catId];
      this.$modal.confirm(`是否确认删除分类【${data.name}】？`)
        .then(() => {
          return logicDelCategory(ids);
        })
        .then(() => {
          this.$modal.msgSuccess("删除成功");
          this.getList();
        })
        .catch(() => {
          this.$modal.msgInfo("已取消删除");
        });
    },
    // 下载方法（若项目中未全局定义，需补充）
    download(url, params, filename) {
      import('@/utils/request').then(request => {
        request({
          url: url,
          method: 'get',
          params: params,
          responseType: 'blob'
        }).then(response => {
          const blob = new Blob([response.data])
          const link = document.createElement('a')
          const url = URL.createObjectURL(blob)
          link.href = url
          link.download = filename
          link.click()
          URL.revokeObjectURL(url)
        })
      })
    }
  }
}
</script>

<style scoped>
/* 容器基础样式 */
.app-container {
  padding: 20px;
  background-color: #f5f7fa;
  min-height: 100vh;
}

/* 操作工具栏样式 */
.operation-bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
  padding: 12px 16px;
  background-color: #fff;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}

.switch-wrapper {
  display: flex;
  align-items: center;
  color: #666;
}

.btn-group {
  display: flex;
  gap: 10px;
}

.btn-with-margin {
  margin-right: 8px;
}

/* 树形组件容器样式 */
.tree-card {
  background-color: #fff;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
  padding: 20px;
  margin-bottom: 20px;
  min-height: 400px;
  display: flex;
  flex-direction: column;
}

/* 树形节点样式 */
.custom-tree {
  flex: 1;
  overflow-y: auto;
  max-height: 600px;
}

.custom-tree-node {
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 100%;
  padding: 4px 0;
  border-radius: 4px;
  transition: background-color 0.2s;
}

.custom-tree-node:hover {
  background-color: #f5f7fa;
}

/* 节点文本层级标识 */
.node-label {
  display: flex;
  align-items: center;
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.level-indent {
  display: inline-block;
  width: 16px;
  height: 1px;
}

.level-line {
  display: inline-block;
  width: 8px;
  height: 1px;
  background-color: #ccc;
  margin-right: 8px;
}

/* 节点操作按钮样式 */
.node-actions {
  opacity: 0;
  transition: opacity 0.2s;
}

.custom-tree-node:hover .node-actions {
  opacity: 1;
}

.action-btn {
  color: #666;
  margin-left: 8px;
  padding: 2px 8px;
  border-radius: 4px;
  transition: all 0.2s;
}

.action-btn:hover {
  color: #1890ff;
  background-color: #e6f4ff;
}

.danger-btn:hover {
  color: #ff4d4f;
  background-color: #fff2f0;
}

/* 空数据样式 */
.empty-tree {
  display: flex;
  justify-content: center;
  align-items: center;
  flex: 1;
  color: #999;
}

/* 分页组件样式 */
.pagination-container {
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 16px;
  background-color: #fff;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}

/* 弹窗样式 */
.custom-dialog .el-dialog__body {
  padding: 20px;
}

.form-container {
  margin-top: 10px;
}

.form-input, .form-select {
  width: 100%;
  border-radius: 4px;
  transition: border-color 0.2s;
}

.form-input:focus, .form-select:focus {
  border-color: #1890ff;
  box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
}

.dialog-footer {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 20px;
}

/* 滚动条美化 */
::-webkit-scrollbar {
  width: 6px;
  height: 6px;
}

::-webkit-scrollbar-track {
  background: #f1f1f1;
  border-radius: 3px;
}

::-webkit-scrollbar-thumb {
  background: #ccc;
  border-radius: 3px;
}

::-webkit-scrollbar-thumb:hover {
  background: #999;
}
</style>